// 线程安全堆栈
#include <exception>
#include <memory>
#include <mutex>
#include <stack>

struct emptyStack: std::exception {
    const char* what() const throw() {
        return "empty stack";
    };
};

template<typename T>
class threadSafeStack {
private:
    std::stack<T> data;
    mutable std::mutex m;
public:
    threadSafeStack(): data(std::stack<T>()) { }
    // copy constructor
    threadSafeStack(const threadSafeStack& other) {
        std::lock_guard<std::mutex> lock(other.m);
        data = other.data;
    }
    threadSafeStack& operator=(const threadSafeStack&) = delete;

    void push(T new_val) {
        std::lock_guard<std::mutex> lock(m);
        data.push(new_val);
    }

    std::shared_ptr<T> pop() {
        std::lock_guard<std::mutex> lock(m);
        // check empty brefore pop
        if (data.empty()) {
            throw emptyStack();
        }
        // hand return value brefore change stack
        std::shared_ptr<T> const res(std::make_shared<T>(data.top()));
        data.pop();
        return res;
    }

    void pop(T& value) {
        std::lock_guard<std::mutex> lock(m);
        if (data.empty()) {
            throw emptyStack();
        }
        value = data.top();
        data.pop();
    }

    bool empty() const {
        std::lock_guard<std::mutex> lock(m);
        return data.empty();
    }
};